<?php
/**
 * Created by PhpStorm.
 * User: 毛文科
 * Date: 2019/5/23
 * Time: 16:07
 */
namespace app\admin\model;
use Qiniu\Auth;
use Qiniu\Storage\UploadManager;
use think\Request;

require_once env('ROOT_PATH').'/vendor/teg1c/thinkphp-qiniu-sdk/qiniu_php_driver/autoload.php';

class UpFile{
    protected $file = [];
    protected $dirs = 'uploads';
    protected $type = 'all';
    protected $size = 'auto';
    protected $newname='';
    protected $fugai = false;
    public function __construct()
    {
        $this->dirs = rtrim(config('webroot'),'/').'/'.trim($this->dirs,'/').'/'.session('modular');
    }

    /**设置文件
     * @param Request $requery
     * @param bool $tongming
     * @param null $dir
     * @return $this
     */
    public function setFile(Request $requery,$dir=null,$newname=null){
        if($newname){
            $this->newname = $newname;
        }
        if($dir){
            $this->dirs = $dir;
        }
        $this->file = $requery->file();
         return $this;
    }

    /**获取文件
     * @return array
     */
    public function getFile(){
        return $this->file;
    }

    /**获取返回
     * @return mixed
     */
    public function Preservation(){
        $file = $this->getFile();
        foreach ($file as $key=>$value){
            if(!$this->getQiNiu()){
                $name[] = $this->local($value);
            }else{
                $name[] = $this->SevenOxen($value);
            }
        }
        return $name;
    }

    /**本地保存
     * @param $file
     * @return string
     */
    public function local($file){
        $array['yuan_name'] = $file->getinfo()['name'];
        $info = $file->move('.'.$this->dirs);
        $array['new_name']  = $info->getFilename();
        $array['path']      = str_replace("\\","/",rtrim($this->dirs,'/').'/'.$info->getSaveName());
        $array['status'] = 1;
        $array['create_time'] = time();
        $array['id'] = $this->addEnclosure($array);
        return $array;
    }

    /**七牛云存储
     * @param $file
     * @return bool
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public function SevenOxen($file){
        $qiniu = $this->getQiNiu();
        $new = $file->getinfo();
        $types = explode('.',$new['name']);
        $type = end($types);
        $data['yuan_name'] = $new['name'];
        $ak = $qiniu['ak'];
        $sk = $qiniu['sk'];
        $bucket = $qiniu['bucket'];
        $auth = new Auth($ak,$sk);
        $uploadMgr = new UploadManager();
        $filePath = $new['tmp_name'];
        if(!$this->newname){
            $name = uniqid().'.'.$type;
        }else{
            $name = uniqid().$this->newname;
        }
        if($this->fugai){
            $token = $auth->uploadToken($bucket,$name);
        }else{
            $token = $auth->uploadToken($bucket);
        }
        list($ret,$err) = $uploadMgr->putFile($token,$name,$filePath);
        if($err!==null){
            return false;
        }else{
            $data['new_name'] = $name;
        }
        $data['new_name'] = $name;
        $data['path'] = str_replace("\\","/",$qiniu['url'].'/'.$name);
        $data['create_time'] = time();
        $data['status'] = 1;
        $data['id'] = $this->addEnclosure($data);
        return $data;
    }

    public function deleteSevenOxen($value){
        $qiniu = $this->getQiNiu();
        $key = $value['new_name'];
        $ak = $qiniu['ak'];
        $sk = $qiniu['sk'];
        $bucket  = $qiniu['bucket'];
        $auth = new Auth($ak,$sk);
        $bucketManager = new \Qiniu\Storage\BucketManager($auth);
        $err = $bucketManager->delete($bucket,$key);
        if($err){
            return false;
        }else{
            return true;
        }
    }

    /**检查是否使用七牛云存储
     * @return bool
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public function getQiNiu(){
        $data = QiNiu::where('status',1)->findOrEmpty()->toArray();
        if($data){
            return $data;
        }else{
            return false;
        }
    }

    /**添加到附件表
     * @param array $array
     * @return bool|mixed
     */
    public function addEnclosure($array=[]){
//        $url = '../application/'.session('modular').'/view'.$array['path'];
//        $url = rtrim(str_replace($array['new_name'],'',$url),'/');
//        if(!is_dir($url)){
//            chmod('../application/'.session('modular'),0777);
//            mkdir(rtrim(str_replace($array['new_name'],'',$url),'/'),0777,true);
//        }
//        copy('.'.$array['path'],'../application/'.session('modular').'/view'.$array['path']);
        if($array){
            $data = Enclosure::create($array);
            return $data->id;
        }else{
            return false;
        }
    }

    /**删除文件
     * @param $id
     * @param bool $true
     * @return bool
     * @throws \think\Exception
     * @throws \think\exception\PDOException
     */
    static public function delFile($id,$true=false){
        $obj = new UpFile();
        if($true){
            $data = Enclosure::where('id','in',$id)->select()->toArray();
            foreach ($data as $value){
                if(strstr($value['path'],'http://')||strstr($value['path'],'https://')){
                    $obj->deleteSevenOxen($value);
                }else{
                    $obj->deleteFile($value['path']);
                }
            }
            if(Enclosure::where('id','in',$id)->delete()){
                return true;
            }else{
                return false;
            }
        }else{
            if(Enclosure::where('id','in',$id)
                ->update([
                   'status'=>0
                ])){
                return true;
            }else{
                return false;
            }
        }
    }

    /**删除文件
     * @param $filepath
     */
    public function deleteFile($filepath){
        if(is_file('.'.$filepath)){
            chmod('.'.$filepath,0777);
            unlink('.'.$filepath);
        }
        if(is_file('../application/'.session('modular').'/view'.$filepath)){
            chmod('../application/'.session('modular'),0777);
            unlink('../application/'.session('modular').'/view'.$filepath);
        }
    }

    /**分片上传文件
     * @param $tmp
     * @param $he
     * @param null $fname
     * @return array
     */
    public static function Fragmentation($tmp,$he,$fname=null){
        header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
        header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
        header("Content-type: text/html; charset=gbk32");
        header("Cache-Control: no-store, no-cache, must-revalidate");
        header("Cache-Control: post-check=0, pre-check=0", false);
        header("Pragma: no-cache");
        $folder = input('folder');
        if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
            exit; // finish preflight CORS requests here
        }
        if ( !empty($_REQUEST[ 'debug' ]) ) {
            $random = rand(0, intval($_REQUEST[ 'debug' ]) );
            if ( $random === 0 ) {
                header("HTTP/1.0 500 Internal Server Error");
                exit;
            }
        }
        // header("HTTP/1.0 500 Internal Server Error");
        // exit;
        // 5 minutes execution time
        set_time_limit(5 * 60);
        // Uncomment this one to fake upload time
        usleep(5000);
        // Settings
//        $targetDir = './fenpian'.DIRECTORY_SEPARATOR.'file_material_tmp';            //存放分片临时目录
        $targetDir = $tmp;
        if($folder){
            $uploadDir = $he.DIRECTORY_SEPARATOR.date('Ymd');
        }else{
            $uploadDir = $he.DIRECTORY_SEPARATOR.date('Ymd');    //分片合并存放目录
        }

        $cleanupTargetDir = true; // Remove old files
        $maxFileAge = 5 * 3600; // Temp file age in seconds

        // Create target dir
        if (!file_exists($targetDir)) {
            mkdir($targetDir,0777,true);
        }
        // Create target dir
        if (!file_exists($uploadDir)) {
            mkdir($uploadDir,0777,true);
        }
        // Get a file name
        if (isset($_REQUEST["name"])) {
            $fileName = $_REQUEST["name"];
        } elseif (!empty($_FILES)) {
            $fileName = $_FILES["file"]["name"];
        } else {
            $fileName = uniqid("file_");
        }
        $oldName = $fileName;

        $fileName = iconv('UTF-8','gb2312',$fileName);
        $filePath = $targetDir . DIRECTORY_SEPARATOR . $fileName;
        // $uploadPath = $uploadDir . DIRECTORY_SEPARATOR . $fileName;
        // Chunking might be enabled
        $chunk = isset($_REQUEST["chunk"]) ? intval($_REQUEST["chunk"]) : 0;
        $chunks = isset($_REQUEST["chunks"]) ? intval($_REQUEST["chunks"]) : 1;
        // Remove old temp files
        if ($cleanupTargetDir) {
            if (!is_dir($targetDir) || !$dir = opendir($targetDir)) {
                die('{"jsonrpc" : "2.0", "error" : {"code": 100, "message": "Failed to open temp directory111."}, "id" : "id"}');
            }
            while (($file = readdir($dir)) !== false) {
                $tmpfilePath = $targetDir . DIRECTORY_SEPARATOR . $file;
                // If temp file is current file proceed to the next
                if ($tmpfilePath == "{$filePath}_{$chunk}.part" || $tmpfilePath == "{$filePath}_{$chunk}.parttmp") {
                    continue;
                }
                // Remove temp file if it is older than the max age and is not the current file
                if (preg_match('/\.(part|parttmp)$/', $file) && (filemtime($tmpfilePath) < time() - $maxFileAge)) {
                    unlink($tmpfilePath);
                }
            }
            closedir($dir);
        }
        // Open temp file
        if (!$out = fopen("{$filePath}_{$chunk}.parttmp", "wb")) {
            die('{"jsonrpc" : "2.0", "error" : {"code": 102, "message": "Failed to open output stream222."}, "id" : "id"}');
        }
        if (!empty($_FILES)) {
            if ($_FILES["file"]["error"] || !is_uploaded_file($_FILES["file"]["tmp_name"])) {
                die('{"jsonrpc" : "2.0", "error" : {"code": 103, "message": "Failed to move uploaded file333."}, "id" : "id"}');
            }
            // Read binary input stream and append it to temp file
            if (!$in = fopen($_FILES["file"]["tmp_name"], "rb")) {
                die('{"jsonrpc" : "2.0", "error" : {"code": 101, "message": "Failed to open input stream444."}, "id" : "id"}');
            }
        } else {
            if (!$in = fopen("php://input", "rb")) {
                die('{"jsonrpc" : "2.0", "error" : {"code": 101, "message": "Failed to open input stream555."}, "id" : "id"}');
            }
        }
        while ($buff = fread($in, 4096)) {
            fwrite($out, $buff);
        }
        fclose($out);
        fclose($in);
        rename("{$filePath}_{$chunk}.parttmp", "{$filePath}_{$chunk}.part");
        $index = 0;
        $done = true;
        for( $index = 0; $index < $chunks; $index++ ) {
            if ( !file_exists("{$filePath}_{$index}.part") ) {
                $done = false;
                break;
            }
        }

        if ($done) {
            $pathInfo = pathinfo($fileName);
            $hashStr = substr(md5($pathInfo['basename']),8,16);
            $hashName = time() . $hashStr . '.' .$pathInfo['extension'];
            $uploadPath = $uploadDir . DIRECTORY_SEPARATOR .$hashName;
            if (!$out = fopen($uploadPath, "wb")) {
                die('{"jsonrpc" : "2.0", "error" : {"code": 102, "message": "Failed to open output stream666."}, "id" : "id"}');
            }
            //flock($hander,LOCK_EX)文件锁
            if ( flock($out, LOCK_EX) ) {
                for( $index = 0; $index < $chunks; $index++ ) {
                    if (!$in = fopen("{$filePath}_{$index}.part", "rb")) {
                        break;
                    }
                    while ($buff = fread($in, 4096)) {
                        fwrite($out, $buff);
                    }
                    fclose($in);
                    unlink("{$filePath}_{$index}.part");
                }
                flock($out, LOCK_UN);
            }
            fclose($out);
            $response = [
                'success'=>true,
                'oldName'=>$oldName,
                'filePath'=>$uploadPath,
//                'fileSize'=>$data['size'],
                'fileSuffixes'=>$pathInfo['extension'],          //文件后缀名
//                'file_id'=>$data['id'],
            ];
            return $response;
        }

        // Return Success JSON-RPC response
        die('{"jsonrpc" : "2.0", "result" : null, "id" : "id"}');
    }

    /**复制文件夹
     * @param $source
     * @param $dest
     */
    static public function copydir($source,$dest){
        if (!file_exists($dest)) {
            chmod('../application/'.session('modular'),0777);
            mkdir($dest,0777,true);
        }
//        chmod($dest,0777);
//        chmod($source,0777);
        $handle = opendir($source);
        while (($item = readdir($handle)) !== false) {
            if ($item == '.' || $item == '..') continue;
            $_source = $source . '/' . $item;
            $_dest = $dest . '/' . $item;
            if (is_file($_source)){
                copy($_source, $_dest);
            }
            if (is_dir($_source)){
                UpFile::copydir($_source,$_dest);
            }
        }
        closedir($handle);
    }

    /**获取七牛上传凭证
     * @return bool|string
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public function getQiniuToken(){
        $qiniu = $this->getQiNiu();
        if(!$qiniu){
            return false;
        }
        $ak = $qiniu['ak'];
        $sk = $qiniu['sk'];
        $bucket  = $qiniu['bucket'];
        $auth  = new Auth($ak,$sk);
        $expires = 3600;
        $policy = null;
        $uptoken = $auth->uploadToken($bucket,null,$expires,$policy,true);
        return $uptoken;
    }

    /**分片上传
     * @param $requery tp5请求文件
     * @param $temp 临时文件夹
     * @param $he 合并文件夹
     * @param null $filename 名称
     * @return mixed
     */
    public function FenPian($requery,$temp,$he,$filename=null){
        set_time_limit(5 * 60);
        // Uncomment this one to fake upload time
        usleep(5000);
        $data = $requery->getInfo();
        $names = explode('_',$data['name']);
        $bool = end($names);
        $index =array_slice($names,-3,1);
        $zhong = array_slice($names,-2,1);
        $yuanname = $names[0];
        $newb = explode('.',$yuanname);
        $dirname = $newb[0];
        if(!is_dir(rtrim($temp,'/').'/'.$dirname)){
            chmod(env('ROOT_PATH'),0777);
            mkdir(rtrim($temp,'/').'/'.$dirname,0777,true);
        }
        move_uploaded_file($data['tmp_name'],rtrim($temp,'/').'/'.$dirname.'/'.$yuanname.$index[0]);
        $res['succes'] = $bool;
        $res['yuanname'] = $yuanname;
        $res['path'] = rtrim($temp,'/').'/'.$dirname.'/'.$yuanname.$index[0];
        $res['index'] = $index[0];
        $res['zong'] = $zhong[0];
        if($bool=='true'){
            $unst = '';
            for ($a=0;$a<$zhong[0];$a++){
                    $unst.=file_get_contents(rtrim($temp,'/').'/'.$dirname.'/'.$yuanname.$a);
                    unlink(rtrim($temp,'/').'/'.$dirname.'/'.$yuanname.$a);
            }
            rmdir(rtrim($temp,'/').'/'.$dirname);
            if(!is_dir($he)){
                chmod(env('ROOT_PATH'),0777);
                mkdir($he);
            }
            $res['newname'] = uniqid().'.'.$newb[1];
            if($filename){
                $res['newname'] = $filename;
            }
            file_put_contents(rtrim($he,'/').'/'.$res['newname'],$unst);
            $res['path'] = rtrim($he,'/').'/'.$res['newname'];
        }
        return $res;
    }
}